package com.tanhua.es.service;

import com.tanhua.es.pojo.UserLocationES;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class UserLocationService {

    @Autowired
    private ElasticsearchTemplate esTemplate;

    /**
     * 查询用户的地理位置
     *
     * @param userId
     * @return
     */
    public UserLocationES queryByUserId(Long userId) {
        GetQuery query = new GetQuery();
        query.setId(String.valueOf(userId));
        return this.esTemplate.queryForObject(query, UserLocationES.class);
    }

    /**
     * 更新用户的地理位置
     *
     * @param userId
     * @param longitude
     * @param latitude
     * @param address
     * @return
     */
    public boolean updateUserLocation(Long userId, Double longitude, Double latitude, String address) {
        if (!this.esTemplate.indexExists("tanhua")) {
            // 创建索引
            this.esTemplate.createIndex(UserLocationES.class);
        }
        if (!this.esTemplate.typeExists("tanhua", "user_location")) {
            // 创建type
            this.esTemplate.putMapping(UserLocationES.class);
        }

        // 根据id查询用户的地理位置
        GetQuery query = new GetQuery();
        query.setId(userId.toString());
        UserLocationES ulES = this.esTemplate.queryForObject(query, UserLocationES.class);
        if (ulES == null) {
            // 如果查询出来的数据为空，新建一个对象并且填充字段
            UserLocationES userLocationES = new UserLocationES();
            userLocationES.setUserId(userId);
            userLocationES.setAddress(address);
            userLocationES.setLocation(new GeoPoint(latitude, longitude));
            userLocationES.setCreated(System.currentTimeMillis());
            userLocationES.setUpdated(userLocationES.getCreated());
            userLocationES.setLastUpdated(userLocationES.getCreated());
            IndexQuery indexQuery = new IndexQueryBuilder().withObject(userLocationES).build();
            this.esTemplate.index(indexQuery);// 保存
        } else {
            Map<String, Object> map = new HashMap<>();
            map.put("address", address);
            map.put("updated", System.currentTimeMillis());
            map.put("lastUpdated", ulES.getUpdated());
            map.put("location", new GeoPoint(latitude, longitude));

            UpdateRequest updateRequest = new UpdateRequest();
            updateRequest.doc(map);
            UpdateQuery updateQuery = new UpdateQueryBuilder()
                    .withId(userId.toString())
                    .withClass(UserLocationES.class)
                    .withUpdateRequest(updateRequest).build();
            this.esTemplate.update(updateQuery);// 更新
        }
        return false;
    }

    /**
     * 根据位置搜索
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @param distance  距离(米)
     * @param page      页数
     * @param pageSize  页面大小
     * @return es的分页对象
     */
    public Page<UserLocationES> queryUserFromLocation(Double longitude, Double latitude, Double distance, Integer page, Integer pageSize) {
        String fieldName = "location";

        // 实现了SearchQuery接口，用于组装QueryBuilder和SortBuilder以及Pageable等
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        // 分页
        Pageable pageable = PageRequest.of(page - 1, pageSize);
        nativeSearchQueryBuilder.withPageable(pageable);

        // 定义bool查询
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        // 以某点为中心，搜索指定范围
        GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder(fieldName);
        distanceQueryBuilder.point(latitude,longitude);

        // 定义查询范围的单位：公里
        distanceQueryBuilder.distance(distance/1000, DistanceUnit.KILOMETERS);

        boolQueryBuilder.must(distanceQueryBuilder);
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);

        // 按距离升序
        GeoDistanceSortBuilder geoDistanceSortBuilder = new GeoDistanceSortBuilder(fieldName, latitude, longitude);
        geoDistanceSortBuilder.unit(DistanceUnit.KILOMETERS); // 设置单位
        geoDistanceSortBuilder.order(SortOrder.ASC); //升序
        nativeSearchQueryBuilder.withSort(geoDistanceSortBuilder);

        return this.esTemplate.queryForPage(nativeSearchQueryBuilder.build(),UserLocationES.class);
    }
}
